﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace MengCC.Core.IO
{
    public class IOManager
    {
        private static Dictionary<string, string> inputQueue;
        private static Dictionary<string, StringBuilder> outputQueue;
        private static Dictionary<string, bool> inputLock;
        private static List<IIOEnventHandler> IOEnvents;
        static IOManager()
        {
            inputQueue = new Dictionary<string, string>();
            outputQueue = new Dictionary<string, StringBuilder>();
            inputLock = new Dictionary<string, bool>();
            IOEnvents = new List<IIOEnventHandler>();
        }
        /// <summary>
        /// 添加事件处理
        /// </summary>
        /// <param name="iOEnvent"></param>
        /// <returns></returns>
        public void AddEventHandler(IIOEnventHandler iOEnvent)
        {
            //移除同一个id注册过的
            IOEnvents = IOEnvents.Where(e => e.Id != iOEnvent.Id).ToList();
            IOEnvents.Add(iOEnvent);
        }
        /// <summary>
        /// 移除某个iokey的事件
        /// </summary>
        /// <param name="iokey"></param>
        private void RemoveEnventHandler(string iokey)
        {
            IOEnvents = IOEnvents.Where(e => e.IOKey != iokey).ToList();
        }

        /// <summary>
        /// 输出触发
        /// </summary>
        /// <param name="iokey"></param>
        /// <param name="content"></param>
        private void DoOutput(string iokey,string content)
        {
            var handlers = IOEnvents.Where(e => e.IOKey == iokey && e.EventType == IIOEnventHandler.EventTypeEnum.Output).ToList();
            foreach (var item in handlers)
            {
                try
                {
                    item.OnPush(content);
                }
                catch (Exception)
                {
                    //
                }
            }
        }
        /// <summary>
        /// 输入触发
        /// </summary>
        /// <param name="iokey"></param>
        /// <param name="content"></param>
        private void DoInput(string iokey, string content)
        {
            var handlers = IOEnvents.Where(e => e.IOKey == iokey && e.EventType == IIOEnventHandler.EventTypeEnum.Input).ToList();
            foreach (var item in handlers)
            {
                try
                {
                    item.OnPush(content);
                }
                catch (Exception)
                {
                    //
                }
            }
        }


        /// <summary>
        /// 获取输入锁状态
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private bool GetLock(string key)
        {
            if (!inputLock.ContainsKey(key))
            {
                inputLock.Add(key, false);
            }
            return inputLock[key];
        }

        /// <summary>
        /// 设置输入锁
        /// </summary>
        /// <param name="key"></param>
        /// <param name="isLock"></param>
        private void SetLock(string key, bool isLock)
        {
            if (!inputLock.ContainsKey(key))
            {
                inputLock.Add(key, isLock);
                return;
            }
            inputLock[key] = isLock;
        }



        /// <summary>
        /// 删除队列
        /// </summary>
        /// <param name="key"></param>
        public void RemoveQueue(string key)
        {
            lock ("RemoveQueue")
            {
                if (inputQueue.ContainsKey(key)) inputQueue.Remove(key);
                if (outputQueue.ContainsKey(key)) outputQueue.Remove(key);
                RemoveEnventHandler(key);
            }
        }

        /// <summary>
        /// 插入输入队列
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void EnqueueInput(string key, string value)
        {
            lock ($"EnqueueInput-{key}")
            {
                //if (GetLock(key)) return;
                //if (!inputQueue.ContainsKey(key)) inputQueue.Add(key, value);
                //else inputQueue[key] = value;
                //每次接收一次输入则锁定输入
                //SetLock(key, true);
                //触发输入事件
                DoInput(key, value);
            }


        }
        /// <summary>
        /// 插入输出队列
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void EnqueueOutput(string key, string value)
        {
            lock ($"EnqueueOutput-{key}")
            {
                if (!outputQueue.ContainsKey(key)) outputQueue.Add(key, new StringBuilder());
                outputQueue[key].AppendLine(value);
                //每次输出都解锁输入，并清除现有的输入
                SetLock(key, false);
                if (inputQueue.ContainsKey(key)) inputQueue[key] = string.Empty;
                //触发输出事件
                DoOutput(key, value);
            }
        }
        /// <summary>
        /// 从输入队列出列
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        //[Obsolete("通过添加事件获取输入")]
        //public string DequeueInput(string key)
        //{
        //    while (!inputQueue.ContainsKey(key) || string.IsNullOrEmpty(inputQueue[key])) Thread.Sleep(100);
        //    var result = inputQueue[key];
        //    inputQueue[key] = string.Empty;
        //    SetLock(key, false);
        //    return result;
        //}

        /// <summary>
        /// 从输出队列出列
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string DequeueOutput(string key)
        {
            if (outputQueue.ContainsKey(key))
                return outputQueue[key].ToString();
            return string.Empty;
        }
        /// <summary>
        /// 获取默认的事件处理
        /// </summary>
        /// <param name="iOKey"></param>
        /// <param name="handler"></param>
        /// <param name="eventType"></param>
        /// <returns></returns>
        public IIOEnventHandler GetDefaultIOEnventHandler(string Id,string iOKey, Action<string> handler, IIOEnventHandler.EventTypeEnum eventType)
        {
            return new DefaultIOEnventHandler(handler, iOKey, eventType) { Id=Id};
        }
    }
}
